const cron = require('node-cron');
const { pool } = require('./database');
const emailService = require('./utils/emailService');
const excelService = require('./utils/excelService');

/**
 * 定时任务调度器
 * 负责管理所有定时任务
 */
class Scheduler {
  constructor() {
    this.tasks = new Map();
    this.isRunning = false;
  }

  /**
   * 启动所有定时任务
   */
  start() {
    if (this.isRunning) {
      console.log('⚠️  定时任务已在运行中');
      return;
    }

    console.log('🕐 启动定时任务调度器...');
    
    // 每天00:00更新预约号池数据
    this.addTask('update-appointment-pools', '0 0 * * *', this.updateAppointmentPools.bind(this));
    
    // 每天01:00清理过期数据
    this.addTask('cleanup-expired-data', '0 1 * * *', this.cleanupExpiredData.bind(this));
    
    // 每天18:00发送预约数据邮件
    this.addTask('send-appointment-report', '0 18 * * *', this.sendAppointmentReport.bind(this));
    
    // 每小时检查号池状态
    this.addTask('check-pool-status', '0 * * * *', this.checkPoolStatus.bind(this));
    
    this.isRunning = true;
    console.log('✅ 定时任务调度器启动成功');
  }

  /**
   * 停止所有定时任务
   */
  stop() {
    if (!this.isRunning) {
      console.log('⚠️  定时任务未运行');
      return;
    }

    console.log('🛑 停止定时任务调度器...');
    
    this.tasks.forEach((task, name) => {
      task.destroy();
      console.log(`✅ 已停止任务: ${name}`);
    });
    
    this.tasks.clear();
    this.isRunning = false;
    console.log('✅ 定时任务调度器已停止');
  }

  /**
   * 添加定时任务
   * @param {string} name - 任务名称
   * @param {string} schedule - cron表达式
   * @param {Function} callback - 任务回调函数
   */
  addTask(name, schedule, callback) {
    if (this.tasks.has(name)) {
      console.log(`⚠️  任务 ${name} 已存在，将被覆盖`);
    }

    const task = cron.schedule(schedule, callback, {
      scheduled: false,
      timezone: 'Asia/Shanghai'
    });

    this.tasks.set(name, task);
    task.start();
    
    console.log(`✅ 已添加定时任务: ${name} (${schedule})`);
  }

  /**
   * 移除定时任务
   * @param {string} name - 任务名称
   */
  removeTask(name) {
    const task = this.tasks.get(name);
    if (task) {
      task.destroy();
      this.tasks.delete(name);
      console.log(`✅ 已移除任务: ${name}`);
    } else {
      console.log(`⚠️  任务 ${name} 不存在`);
    }
  }

  /**
   * 获取任务状态
   */
  getStatus() {
    const status = {
      isRunning: this.isRunning,
      tasks: Array.from(this.tasks.keys())
    };
    return status;
  }

  /**
   * 每天00:00更新预约号池数据
   */
  async updateAppointmentPools() {
    console.log('🔄 开始执行预约号池更新任务...');
    
    try {
      // 获取所有启用的医院
      const [hospitals] = await pool.execute(`
        SELECT id, release_days FROM hospitals WHERE is_available = TRUE
      `);

      if (hospitals.length === 0) {
        console.log('ℹ️  没有启用的医院，跳过号池更新');
        return;
      }

      let totalUpdated = 0;
      const today = new Date();
      
      for (const hospital of hospitals) {
        console.log(`🏥 处理医院 ${hospital.id}，放号天数: ${hospital.release_days}`);
        
        // 获取该医院的所有启用医生
        const [doctors] = await pool.execute(`
          SELECT id FROM doctors 
          WHERE hospital_id = ? AND is_available = TRUE
        `, [hospital.id]);

        for (const doctor of doctors) {
          try {
            // 调用存储过程生成号池
            const [result] = await pool.execute('CALL GenerateAppointmentPools(?, ?, ?)', [
              hospital.id,
              doctor.id,
              today
            ]);

            const generatedDays = result[0][0]?.generated_days || 0;
            totalUpdated += generatedDays;
            
            console.log(`👨‍⚕️ 医生 ${doctor.id} 生成了 ${generatedDays} 天的号池`);
          } catch (error) {
            console.error(`❌ 医生 ${doctor.id} 号池生成失败:`, error.message);
          }
        }
      }

      console.log(`✅ 预约号池更新完成，共生成 ${totalUpdated} 天的号池数据`);
      
      // 记录任务执行日志
      await this.logTaskExecution('update-appointment-pools', true, `成功生成 ${totalUpdated} 天的号池数据`);
      
    } catch (error) {
      console.error('❌ 预约号池更新任务失败:', error);
      await this.logTaskExecution('update-appointment-pools', false, error.message);
    }
  }

  /**
   * 每天01:00清理过期数据
   */
  async cleanupExpiredData() {
    console.log('🧹 开始执行数据清理任务...');
    
    try {
      const today = new Date();
      const thirtyDaysAgo = new Date(today.getTime() - 30 * 24 * 60 * 60 * 1000);
      
      // 清理过期的预约号池（30天前）
      const [poolResult] = await pool.execute(`
        DELETE FROM appointment_pools 
        WHERE appointment_date < ? AND used_quota = 0
      `, [thirtyDaysAgo]);
      
      // 清理过期的预约记录（30天前且已取消或完成）
      const [appointmentResult] = await pool.execute(`
        DELETE FROM appointments 
        WHERE appointment_date < ? AND status IN ('cancelled', 'completed')
      `, [thirtyDaysAgo]);
      
      console.log(`✅ 数据清理完成，清理了 ${poolResult.affectedRows} 个过期号池，${appointmentResult.affectedRows} 个过期预约`);
      
      await this.logTaskExecution('cleanup-expired-data', true, 
        `清理了 ${poolResult.affectedRows} 个过期号池，${appointmentResult.affectedRows} 个过期预约`);
        
    } catch (error) {
      console.error('❌ 数据清理任务失败:', error);
      await this.logTaskExecution('cleanup-expired-data', false, error.message);
    }
  }

  /**
   * 每小时检查号池状态
   */
  async checkPoolStatus() {
    console.log('🔍 开始执行号池状态检查任务...');
    
    try {
      const today = new Date();
      const tomorrow = new Date(today.getTime() + 24 * 60 * 60 * 1000);
      
      // 检查今天和明天的号池状态
      const [pools] = await pool.execute(`
        SELECT 
          ap.id,
          ap.hospital_id,
          ap.doctor_id,
          ap.appointment_date,
          ap.time_slot_type,
          ap.total_quota,
          ap.used_quota,
          ap.available_quota,
          ap.is_available,
          h.name as hospital_name,
          d.name as doctor_name
        FROM appointment_pools ap
        LEFT JOIN hospitals h ON ap.hospital_id = h.id
        LEFT JOIN doctors d ON ap.doctor_id = d.id
        WHERE ap.appointment_date BETWEEN ? AND ?
        ORDER BY ap.appointment_date, ap.time_slot_type
      `, [today, tomorrow]);

      let warningCount = 0;
      
      for (const pool of pools) {
        // 检查号池是否已满但状态仍为可用
        if (pool.available_quota <= 0 && pool.is_available) {
          console.log(`⚠️  号池 ${pool.id} (${pool.hospital_name} - ${pool.doctor_name}) 已满但状态仍为可用`);
          warningCount++;
        }
        
        // 检查号池是否有剩余但状态为不可用
        if (pool.available_quota > 0 && !pool.is_available) {
          console.log(`⚠️  号池 ${pool.id} (${pool.hospital_name} - ${pool.doctor_name}) 有剩余但状态为不可用`);
          warningCount++;
        }
      }

      if (warningCount === 0) {
        console.log('✅ 号池状态检查完成，未发现异常');
      } else {
        console.log(`⚠️  号池状态检查完成，发现 ${warningCount} 个异常`);
      }
      
    } catch (error) {
      console.error('❌ 号池状态检查任务失败:', error);
    }
  }

  /**
   * 记录任务执行日志
   * @param {string} taskName - 任务名称
   * @param {boolean} success - 是否成功
   * @param {string} message - 执行消息
   */
  async logTaskExecution(taskName, success, message) {
    try {
      await pool.execute(`
        INSERT INTO task_logs (task_name, success, message, executed_at)
        VALUES (?, ?, ?, NOW())
      `, [taskName, success, message]);
    } catch (error) {
      console.error('记录任务日志失败:', error);
    }
  }

  /**
   * 每天18:00发送预约数据邮件
   */
  async sendAppointmentReport() {
    console.log('📧 开始执行预约数据邮件发送任务...');
    
    try {
      // 获取邮件配置
      const emailConfig = await this.getEmailConfig();
      
      if (!emailConfig || !emailConfig.isEnabled) {
        console.log('ℹ️  邮件发送功能未启用，跳过邮件发送');
        return;
      }

      // 获取所有启用的医院
      const [hospitals] = await pool.execute(`
        SELECT id, name FROM hospitals WHERE is_available = TRUE
      `);

      if (hospitals.length === 0) {
        console.log('ℹ️  没有启用的医院，跳过邮件发送');
        return;
      }

      const today = new Date();
      const yesterday = new Date(today.getTime() - 24 * 60 * 60 * 1000);
      const startDate = yesterday.toISOString().split('T')[0];
      const endDate = today.toISOString().split('T')[0];

      let totalSent = 0;

      for (const hospital of hospitals) {
        try {
          console.log(`📊 生成医院 ${hospital.name} 的预约数据报告...`);
          
          // 生成Excel报告
          const report = await excelService.generateAppointmentReport({
            hospitalId: hospital.id,
            startDate,
            endDate,
            hospitalName: hospital.name
          });

          // 发送邮件
          const result = await emailService.sendAppointmentReport(
            emailConfig.recipientEmail,
            report.buffer,
            report.fileName,
            report.statistics
          );

          if (result.success) {
            console.log(`✅ 医院 ${hospital.name} 的预约数据报告发送成功`);
            totalSent++;
          } else {
            console.error(`❌ 医院 ${hospital.name} 的预约数据报告发送失败:`, result.error);
          }
        } catch (error) {
          console.error(`❌ 处理医院 ${hospital.name} 邮件失败:`, error.message);
        }
      }

      console.log(`✅ 预约数据邮件发送完成，共发送 ${totalSent} 封邮件`);
      
      // 记录任务执行日志
      await this.logTaskExecution('send-appointment-report', true, `成功发送 ${totalSent} 封预约数据邮件`);
      
    } catch (error) {
      console.error('❌ 预约数据邮件发送任务失败:', error);
      await this.logTaskExecution('send-appointment-report', false, error.message);
    }
  }

  /**
   * 获取邮件配置
   */
  async getEmailConfig() {
    try {
      // 从环境变量或数据库获取邮件配置
      const config = {
        isEnabled: process.env.EMAIL_ENABLED === 'true',
        recipientEmail: process.env.EMAIL_RECIPIENT || 'admin@hospital.com',
        senderEmail: process.env.SMTP_USER || 'your_email@qq.com'
      };

      // 如果配置了数据库存储，可以从数据库读取
      // const [rows] = await pool.execute('SELECT * FROM email_config WHERE id = 1');
      // if (rows.length > 0) {
      //   config = { ...config, ...rows[0] };
      // }

      return config;
    } catch (error) {
      console.error('获取邮件配置失败:', error);
      return null;
    }
  }

  /**
   * 手动执行任务
   * @param {string} taskName - 任务名称
   */
  async executeTask(taskName) {
    console.log(`🔄 手动执行任务: ${taskName}`);
    
    switch (taskName) {
      case 'update-appointment-pools':
        await this.updateAppointmentPools();
        break;
      case 'cleanup-expired-data':
        await this.cleanupExpiredData();
        break;
      case 'send-appointment-report':
        await this.sendAppointmentReport();
        break;
      case 'check-pool-status':
        await this.checkPoolStatus();
        break;
      default:
        console.log(`❌ 未知任务: ${taskName}`);
    }
  }
}

// 创建全局调度器实例
const scheduler = new Scheduler();

module.exports = scheduler;
